package com.xyzwps.paimon.furina.modules.tag

import com.xyzwps.paimon.furina.common.DateTimeUtil
import com.xyzwps.paimon.furina.common.value.PageSize
import kotlinx.datetime.LocalDateTime
import org.jetbrains.exposed.dao.id.LongIdTable
import org.jetbrains.exposed.sql.Column
import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.insertAndGetId
import org.jetbrains.exposed.sql.kotlin.datetime.datetime
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.and
import org.springframework.stereotype.Repository

@Repository
class TagRepository {

    private val t = TagTable

    fun create(domain: Int, name: String): Tag {
        t.insertAndGetId {
            it[t.domain] = domain
            it[t.name] = name
            it[t.createTime] = DateTimeUtil.currentLocalDateTime()
            it[t.deleteTime] = null
        }
        return this.findByDomainAndName(domain, name)!!
    }

    fun findByDomainAndName(domain: Int, name: String): Tag? = t
        .select { (t.domain eq domain) and (t.name eq name) }
        .map { t.toTag(it) }
        .firstOrNull()

    fun findByPrefix(domain: Int, prefix: String, size: PageSize): List<Tag> = t
        .select { (t.domain eq domain) and (t.name like "${prefix}%") and (t.deleteTime.isNull()) }
        .limit(size.value)
        .map { t.toTag(it) }
        .toList()

    fun findByIds(domain: Int, ids: List<Long>): List<Tag> = if (ids.isEmpty()) emptyList() else t
        .select { (t.domain eq domain) and (t.id inList ids) }
        .map { t.toTag(it) }
        .toList()
}

object TagTable : LongIdTable("tag") {
    val domain: Column<Int> = integer("domain")
    val name: Column<String> = varchar("name", Tag.NAME_MAX_LENGTH)
    val createTime: Column<LocalDateTime> = datetime("create_time")
    val deleteTime: Column<LocalDateTime?> = datetime("delete_time").nullable()

    init {
        uniqueIndex(customIndexName = "uk_domain_tags", domain, name)
    }

    fun toTag(row: ResultRow) = Tag(
        id = row[id].value,
        domain = row[domain],
        name = row[name],
        createTime = row[createTime],
        deleteTime = row[deleteTime]
    )
}